package com.garlicts.framework.rpc;

import com.garlicts.framework.core.FrameworkConstant;
import com.garlicts.framework.common.Request;
import com.garlicts.framework.common.Response;
import com.garlicts.framework.config.PropertiesProvider;
import com.garlicts.framework.registry.ServiceDiscovery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

public class RpcClientProxy {

	private static final Logger LOGGER = LoggerFactory.getLogger(RpcClientProxy.class);

	@SuppressWarnings("unchecked")
	public static <T> T create(final Class<?> interfaceClass, final String interfaceName) {
		
		// 创建动态代理对象
		return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass }, new InvocationHandler() {
			
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// 创建 RPC 请求对象并设置请求属性
						Request request = new Request();
						request.setRequestId(UUID.randomUUID().toString());
						request.setInterfaceName(interfaceName);
						request.setMethodName(method.getName());
						request.setParameterTypes(method.getParameterTypes());
						request.setParameters(args);


						String zkAddressStr = PropertiesProvider.getString(FrameworkConstant.CUSTOM_ZOOKEEPER_ADDRESS);
						String[] zkAddressArr = zkAddressStr.split(",");
						ServiceDiscovery serviceDiscovery = ServiceDiscoveryFactory.getServiceDiscovery(zkAddressArr[0]);
						// 获取 RPC 服务地址
						String serviceAddress = null;
						if (serviceDiscovery != null) {
							serviceAddress = serviceDiscovery.discover();
							LOGGER.debug("discover service: {}", serviceAddress);
						}
						if (StringUtils.isEmpty(serviceAddress)) {
							throw new RuntimeException("server address is empty");
						}
						
						// 从 RPC 服务地址中解析主机名与端口号
						String[] array = StringUtils.splitByWholeSeparator(serviceAddress, ":");
						String host = array[0];
						int port = Integer.parseInt(array[1]);
						
						// 创建 RPC 客户端对象并发送 RPC 请求
						RpcClient client = new RpcClient(host, port);
						long time = System.currentTimeMillis();
						Response response = client.send(request);
						LOGGER.debug("time: {}ms", System.currentTimeMillis() - time);
						if (response == null) {
							throw new RuntimeException("response is null");
						}
						// 返回 RPC 响应结果
						if (response.hasException()) {
							throw response.getException();
						} else {
							return response.getResult();
						}
					}
					
				});
		
	}

}
